Demos:
Corrections:
As people who know me, could testify - I love playing (and creating) computer games. In particular I like strategy games (like Age of Empires and Home World) and simulation games (like SimCity). To a certain degree both types of games share many similar elements - such as specific environmental conditions, limitations, resources, technologies, tasks and controlling principals. These are the things that define a simulation style game. They provide the player the ability to exercise "what if" scenarios with a controlled model. Experimenting with dynamic conditions that control a system is the essence of the simulation.
While SimCity and Home World are very complex games, which one would not create with Liberty Basic, the language does lend itself to simpler yet interesting simulations. As a hobby I collect simulations. Many of these are classic programs written for some of the earliest computers such as the TRS-80, PET and Atari. I have listings for Star Merchant, Nuclear Power Plant, Jewel Thief, Space Navigation, Conway's Life and many others. These are well suited for translation to Liberty Basic. Likewise they can be inspirational for creating new simulations. In this article I will be introducing the process of creating a simulation.
What specifically are simulations? Any program (or game) that attempts to artificially represent a particular environment. Typically, in most pure form, the player is not permitted to directly control the game (or simulation), but rather they wields control indirectly by manipulating various game parameters. These parameters in turn influence how the simulation controls the various details of the game.
Liberty Basic is an excellent platform for developing simulations. It has a simple, easy to master syntax which is rich in features, including graphics, sprites, a timer, and access to operating system extensions via DLL calls. With little effort someone can easily assemble a nice simulation to experiment with an environment or play an interesting game. Own Tom Nally can attest to the fitness of the language to the task. He has written several top notch simulations in the past, including Ball Sim, Bug Sim, and Boom Sim amoung others.
This article was based on the development of a simulation which draws its roots in the ancient game HAMMURABI. We will explore going from a simple concept to an operationally complete simulation. This is not a beginning programming article. We will be explaining some programming concepts that are useful, but we will assume you have a fair grasp of the language.
Every simulation begins as a concept. Something you want to experiment with or prove. Usually it is fairly basic definition or object; around which your game or simulation is constructed. This simulation is one of growing a society. The inhabitants are creatures I invented called Worbles. The game concept was born out of an earlier game as I mentioned. In the earlier game you plant grain, sell grain and grow your kingdom. As I considered how I would implement my version I wanted to introduce a few more elements of control. I still saw three phases to each round of game play. Growing grain and feeding the worbles was the first. Selling excess grain was the second and then processing yearly events was the last.
I made additional design decisions adding features such as various roles for each worble and a special role called scientist. Scientists worbles can boost worble technology levels making them more productive in their various fields. They come at a price. Assigning worbles to other tasks will not cost you anything, but assigning worbles to the task of research will reduce the treasury.
I found this give and take interesting. Your goal will be to get a whole lot of money, and in order to do that effectively, you must research the various worble occupations. Yet the creation of scientists to do the research reduces your coffers. But I am getting ahead of myself.
As I developed the ideas in mind and on paper I realized I needed a reliable format to document the design choices. This is where a design document can be invaluable. I added many features and sketched a GUI for the game and integrated these into my design document. Elsewhere in this issue of the newsletter you will find a design document aimed at game developers (reprinted with permission). This was the perfect vehicle for my purposes. What follows is the thumbnail sketch of this game at design time integrated into that format.
"Worbles wobble but they don't grow old" (Ok I made that up…)
General Features -
Gameplay -
The game is played in a static environment viewed as statistical portals into the world of the Worbles. One imagines the worbles as semi-intellegent, capable of learning, building shelters, growing food and feeding their own. As the player you will control how many worbles are assigned to doing the various tasks required by the society.
The world has a predefined set of rules that govern the hatching, life and death of worbles. These are the rules the simulation enforces:
In addition to the rules, several random events can occur which will effect your worble population. These are truly random events and can not be predicted. These are:

None at design time
Worble types -
Science Types -
End Game Conditions -
Key Variables:
scale (scale of assignment of worbles to jobs and research) worbles (current total worbles) born (number of worbles born for current year) year (current year) phase (phase of the user entry: 1 = feed, 2 = sell, 3 = next year) grain (grain harvested for current year) cash (gold units on hand)
worble work assignments
idlework farmers nursery scientists builders
scientist study unit assignments
sunits (total study units) sidle (idle study units) snursery (nursery study units) sfarming (farming study units) sscience (scientist study units) sbuilder (builder study units) smarket (marketing study units)
Current worble tech levels
tlnursery (tech level of nusery) tlfarming (tech level of farming) tlscience (tech level of scientist) tlbuilder (tech level of builder) tlmarket (tech level of marketing)
Progress to the next tech level in study units
prognursery (nursery) progfarming (farming) progscience (scientist) progbuilder (builders) progmarket (marketing)
I went from the design document to my favorite graphics program (well I actually used Microsoft Visio and Microsoft Image Composer) to created the various elements of the game GUI. These were in my mind clearly GUI components that could be designed ahead of time and simply drawn to the screen.
I used Alyce Watson's fantastic Liberty Basic Workshop (LBW) to create the basic window, graphicbox and the 18 or so command buttons I would need. LBW generated the skeleton program on which the game would develop. I knew going in that this game would have quite a few lines of code. For this reason I chose to subdivide the program into several sections:
This division of code helps me avoid the probability of spaghetti coding. LBW provided most of the that fell into the Window Creation section. There were a number of screen update routines that needed to be developed. The rest of the program stood as an empty slate. There was a lot of thought that went into various bits of code (I fear that this may not be too obvious when you see my hideous coding). I am not going to be able to explain the whole program line by line here. What I hope to do is explain some neat tricks I used, show what is unique in a simulation and give you some tips for writing your own games. I worked with some LB commands I have never used to make this possible. You should benefit.
Let me point out that I chose to create the game around a standard window with an oversized graphicbox, rather than a graphic window. I initially began with a graphic window, but realized that the other worked better. I think that the decision was forced (in my mind at the time) by the fact that I wanted to map the graphicbox handle for use in subs and functions. Looking back I suspect that I could have done the same to a graphics window, but I was having problems initially. This final approach really worked great once I got a couple things straight. Frankly a whole article on the subject of maphandle would be great.
At design time I chose to put my game information update routines into a sub program. I knew I wanted this. When I first tried it I found that I was getting errors since the sub program did not know about the window elements which I was writing data to. I quickly concluded I needed to use Maphandle to move the window's graphicbox handle into a variable that I could pass into a sub program or function.
It is important to map the handle right after the window is opened. After mapping the handle you must refer to the window element by the mapped name from then on.
The graphicbox presented new problems. It has a border that I did not like to see. It is possible to issue some API calls or maybe even a stylebit call to remove the border, but this seemed like a lot of work. I simply tweaked the code to create the element to position it a bit up and left of the window boarder and it was a bit larger than the entire window, putting the border out of sight.
That concept can be seen in this graphic where the window is shown, and an simulated graphicbox extends beyond the window limits:

This is a simple and effective trick for removing a border of a graphicbox with minimal fuss.
There is a lot of data to track in nearly any simulation. I found that to be true here. Data upon data it seemed. There were worbles, and then there were different types of worbles (idle, hatchery worker, farmer, scientist, builder), then there things the scientist worbles studied, the builder worbles built, the hatchery worker worbles hatched and the farmers farmed. Each scientist worble had things they studied and each of those things had a level and a percentage complete to the next level. Data elements multiplied.
In order to keep it all straight I grouped them together, assigned initial values and labeled them with comments when ever I thought greater clarity was needed. This all happened in the beginning of the program (as you will notice if you study the code). I suppose this is too simple to mention, but people are always asking "how do I keep track of such and such in my game?" - Here is the example. You have to have a variable and save the value and update it all the time. A no brainer.
As I mentioned earlier, I decided early to use sub programs to draw the data updates to the screen. Initially I wrote these passing ten, a doze, and in one case 28 data items in the call. I have never passed so many items in a single call. I found out the hard way that you can NOT put a continuation character in the definition of a sub program or function. All of those items must go on a single line. This was not so bad, but I reached a point where I needed to update five of the elements in a single function. I considered an array, but the remembered GLOBAL. It is a new command in LB4.x. I moved 30 variables into a global statement. The down stream result of using global was that it allowed me to clean up some of my heavily loaded sub program and function statements, making them more manageable.
I do not advocate the use of GLOBAL for every variable in you program. It is a two edged sword. While it can reveal your variable to a sub program or function where it can be changed on purpose, it is possible to introduce bugs by presuming the same variable is safe to alter in another sub program, when in fact it is not. Here are some good guidelines to consider:
I should note a slightly frustrating experience I had using global for the first time. Having used many languages, some of which feature a global statement, I presumed that I could split my variables into groups with multiple global statement, something like this:
Global var1, var2, var3, var4, etc
Global var11, var12, var13, var14, etc
Global var21, var22, var23, var24, etc
Unfortunately this proved to be wrong. The helpfile does not mention this, but Liberty Basic only support the use of a single GLOBAL statement in your code. You must wrap your variables from line to line using line continuation should the lot of them not fit on a single line:
global idlework, farmers, nursery, scientists, builders, worbles, _
sunits, sidle, snursery, sfarming, sscience, sbuilder, smarket, _
tlnursery, tlfarming, tlscience, tlbuilder, tlmarket, _
prognursery, progfarming, progscience, progbuilder, progmarket
Another concern of all this data is the interdependencies of various data elements and the significance of reducing worbles. This was a challenge I found myself always confronting and fixing while I developed the game. If 10 worbles die, then they must be removed from somewhere. Each has tasks. I found I needed to create a routine to randomly remove the worbles from various assigned tasks (by the way the odds are much greater that you will lose scientist worbles rather than the other worker worbles - this is by design).
If I removed farmer worbles, I had to recalculate the total acres under cultivation. If builder worbles were removed then dwelling capacity had to be recalculated. It became even more complex if scientist worbles were removed. This necessitated a recalculation of the available study units, then I found I needed another routine to reduce the study units from various areas of study in a random manner.
This data dependency required great care when handling the various data. It is something to consider when creating games and simulations. These are areas where bugs easily creep into your program and they can be hard to spot. I am sure I have some.
Many experienced Liberty Basic programmers know how to trap the left mouse down button using the EVENT command directed at a graphicbox. For the game to work I needed to know when the user clicked one of my navigation buttons or the scale buttons. It was easy to trap the event, but I have designed the GUI in a other program. I did not known the coordinates I needed to make this little bit of magic possible. As desperate as that sounds, there is a very simple solution - get you code running and code the portion that detects the mouse click. Get the X and Y coordinate and pop them up into a notice box. It looks like this:
#gbx$ "when leftButtonDown [screenClick]"
[screenClick]
x = MouseX
y = MouseY
notice "MouseX = " + str$(x) + ", MouseY = "+ str$(y)
wait
Write down those coordinates, and then replace the code above with something like:
if (y > 7 and y < 81) and (x > 349 and x < 469) then
…some code
wait
end if
if (y > 7 and y < 81) and (x > 468 and x < 582) then
…some code
wait
end if
if (y > 7 and y < 81) and (x > 581 and x < 694) then
…some code
wait
end if
Another interesting challenge to solve was the display of numeric data in a right justified column. It is pretty easy to print data to a graphics window and justify it left, do this by simply starting every line of text at the same x coordinate. Or easier yet, use the "\" new line character to simply advance a line at a time.
To align the data right you must know how long the printed text will be on the screen and place it specifically in the correct x and y coordinate so that the trailing end of the text will align with that above and below. This is tricky, but Liberty Basic helps out a lot with a graphics command called StringWidth. It can determine just how many pixels long your text sting will be.
I created the following function to determine the x coordinate to place the text string "value$" so that it will align right at the graphics location "rightx".
function alignRight(value$, rightx, gbx$)
'this function will find the correct x coordinate at which to place
'the passed string so that it will align right at rightx
#gbx$, "stringwidth? value$ width"
alignRight = rightx - width
end function
If you study the code you will find I use this function to align the quantity of worbles assigned to tasks, as well as the study unit assignments. This was a design requirement that I established early in the game design.
Another design requirement that introduced challenge was the printing of text to the notice area below the information window. I realized almost immediately that I would want to place more text there than would fit on a single line. This meant I had to wrap the text. Liberty Basic would not wrap the text for me since I was not using a widget that supported text wrapping - this meant I would have to write my own.
After several attempts I arrived at a fairly elegant solution in the form of a recursive function. These can be tricky to understand, as the function call itself and then again calls itself over and over, breaking the string into components. This allowed me to do in a few lines of code what I originally coded in 50 lines.
At the heart of the function is the stringwidth graphics command again. The word$ function also plays a pivotal role in the function. It extracts the current text line from the multiple text lines for inspection with the stringwidth function. I used a fixed string length of 413 in my routine - you can change that to meet your needs, or pass in the string length as another argument if you would like to reuse this function.
function wrapMsg$(buffer$, msg$, cnt, ln, gbx$)
'recursive word wrapper function
a$ = word$(msg$, cnt)
if a$ <> "######" then
work$ = buffer$ + a$ + " "
curline$ = word$(work$, ln, "\")
#gbx$ "stringwidth? curline$ width"
if width < 413 then
wrapMsg$ = wrapMsg$(work$, msg$, cnt+1, ln, gbx$)
else
work$ = buffer$ + "\" + a$ + " "
wrapMsg$ = wrapMsg$(work$, msg$, cnt+1, ln+1, gbx$)
end if
else
wrapMsg$ = buffer$
end if
end function
Most of the game play is conducted in the main game window. Selling grain is the exception. I had considered creating an area in the main game window where you can select how much grain to sell (and I may still do that in future versions), but without the required real-estate I decided to open a simple dialog window and use standard window widgets such as buttons, a listbox and text labels. Having two game windows open presents problems. What if the used chooses to do nothing with the dialog window, but instead clicks on the game window, shifting focus and covering up the dialog window. After doing this they may cause the sequence of the game to be mixed up as well.
To prevent this I used a modal dialog window. This type of window forces the user to deal with the window as presented before moving on. It is not possible to give the focus back the main program window while the modal dialog window is open.
I know that Liberty Basic has a method of randomly seeding the random number generator from run to run and it is suppose to appear fairly random, but as I tested the game, I became increasingly aware of patterns that each game flowed in, almost as if the seeding was not particularly random. While I have no real evidence of this either way, I decided to seed the random number generator myself. I do this by using the date and seconds since midnight in a short routine to reduce the number to a value between .01 and .99 (inclusive). It seems to produce a fairly random seed and the patterns have since disappeared. Here is my seed function:
function seedGen()
'creates a psuedo-random seed for seeding RND number generator
tm = time$("ms")
tmp = date$("days")
d = val(word$(time$(),3,":")) + 1
tmp = ((tmp/d)/d)
while tm > .99
tm = tm / (tmp+.000000001)
wend
tm$ = using("#.##",tm)
seedGen = val(tm$)
end function
This has been a fun and satisfying project. I wish it did not take so long to finish, as it has put the publishing of the newsletter way behind schedule. That is life I suppose. In the end the game is challenging and fun to play also.
If you are interested in simulations, maybe you will like to play this, and even learn a thing or two from my code. The game in its entirety is located in the newsletter archive - download the newsletter to get it.
Enjoy!